/**
 * \file   hex.cpp
 * \author Fabian Jesus Machado
 * \date   Septiembre de 2011
 * 
 *  Este archivo es parte del proyecto NPASM, un ensamblador para
 * microcontroladores PIC con sintaxis Intel, desarrollado inicialmente
 * por Fabian Machado (fabianjsm@gmail.com, twitter@fabianjsm).
 *  El codigo fuente esta diponible en el repositorio SVN de Google:
 *      http://npasm.googlecode.com/svn/trunk.
 * 
 *  El archivo HEX generado por NPASM posee el formato Intel Hex32,
 * especificado por Intel para transferir archivos.
 *  El formato del archivo se comprende durante los comentarios
 * 
 */
#include <iostream>
#include <stdio.h>
#include <vector>
#include "auxiliar.h"
#include "entorno.h"
#include "mm.h"
#include "hex.h"
using namespace std;

FILE *h;

void nueva_linea()
{
	//fprintf(h, "\r\n");
	fprintf(h, "\n");
}

void linea_hex(size_t i, size_t n, vector<unsigned short> &rom)
{
	unsigned char chk;
	string linea;
	/* 1) prefijo ':' */
	linea = ":";
	/* 2) 2 digitos, cantidad de datos que posee la linea */
	chk = 2*n;
	linea += mkstring("%02X", 2*n);
	/* 3) 4 digitos, direccion */
	chk += (i<<1) & 0xFF;
	chk += (i >> 7) & 0xFF;
	linea += mkstring("%04X", 2*i);
	/* 4) 2 digitos, tipo de linea (0, linea normal) */
	linea += "00";
	/* 5) trama de datos */
	while(n--) {
		unsigned short word = rom[i++];
		unsigned char a , b;
		a = word & 0xFF;
		b = (word >> 8) & 0xFF;
		chk += a;
		chk += b;
		linea += mkstring("%02X", a);
		linea += mkstring("%02X", b);
	}
	/* 6) checksum (numero de verificacion) */
	linea += mkstring("%02X", (int)(0x100 - chk));
	/* 7) salto de linea */
	fprintf(h, "%s", linea.c_str());
	nueva_linea();
}

void generar_hex()
{
	string archivo = Entorno->GetNombreBase() + ".hex";
	h = fopen(archivo.c_str(), "wb");
	vector<unsigned short> &rom = Entorno->GetVectorROM();
	size_t j, max = rom.size();
	/*  El objetivo de esta primer linea es asegurar que parte alta de
	 * la direccion extendida es nula. */
	fprintf(h, ":020000040000FA");
	nueva_linea();
	for(size_t i=0; i<max; i++) {
		if(rom[i] == 0xFFFF)
			continue;
		for(j=1; j<8; j++)
			if(rom[i+j] == 0xFFFF)
				break;
		linea_hex(i, j, rom);
		i += j-1;
	}
	/* Fin de archivo */
	fprintf(h, ":00000001FF");
	nueva_linea();
	fclose(h);
}

